/*
 * Ao utilizar esta classe template deve-se sequir as sequintes regras
 * 0 - A classe T deve ter construtor privado e ser amiga de Singleton<T>
 * 1 - utilzar um ponteiro do tipo T* para armezanar a instância retornada por Singleton<T>::getInstance();
 * 2 - nunca deletar a referência com delete e sim utilizar Singleton<T>::releaseInstance();
 * 
 * Exemplo:
 * 
 * #include "Singleton.h"
 * 
 * class A
 * {
 *    private:
 *       A() {};    //construtor privado
 *    
 *    public:
 *    
 *       friend class Singleton<A>;   //necessário para que a classe template Singleton<A> possa acessar o construtor padrão de A e assim criar um objeto do tipo A
 *     
 *       facaAlgo() {};               //metodo qualquer da classe A
 *   }
 *  
 *  
 *  void funcao(void)
 *  {
 *       A* ponteiro =  Singleton<A>::getInstance();     //pega uma instancia de A
 *       A->facaAlgo();
 *       Singleton<T>::releaseInstance();                //libera a instancia de A;
 *  }
 */
 
#ifndef _SINGLETON_H_
#define _SINGLETON_H_

template<class T>
class Singleton
{
    private:

        static T* instance;
        Singleton(void) {};
        
    public:

    /*
     * Aloca memória para a única instancia
     */
    static T* getInstance(void)
    {
        if(instance == 0)
            instance = new T();
        return instance;
    }
    
    /*
     * Desaloca a memória ocupada pela única instância
     */ 
    static void releaseInstance(void)
    {
        if(instance != 0)
            delete instance;
        instance = 0;
    };
};

template <class T> T* Singleton<T>::instance = 0;

#endif

